package com.von.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.von.entity.UserRole;
import com.von.mapper.RoleMapper;
import com.von.entity.Resource;
import com.von.entity.Role;
import com.von.entity.RoleResource;
import com.von.service.IResourceService;
import com.von.service.IRoleResourceService;
import com.von.service.IRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.von.service.IUserRoleService;
import com.von.vo.RolePage;
import com.von.vo.RoleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author pengzhaofeng
 * @since 2020-05-28
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Autowired
    private IResourceService iResourceService;

    @Autowired
    private IRoleResourceService iRoleResourceService;

    @Autowired
    private IUserRoleService iUserRoleService;

    @Override
    public R<List<Map>> getAll() {
        return R.ok(list().stream().map(role -> {
                    List<Integer> collect = iRoleResourceService.lambdaQuery().eq(RoleResource::getRoleId, role.getId()).list().stream().map(RoleResource::getResourceId).collect(Collectors.toList());
                    JSONObject jsonObject = JSONUtil.parseObj(role);
                    if (CollectionUtil.isNotEmpty(collect)) {
                        jsonObject.set("resource", iResourceService.lambdaQuery().in(Resource::getId, collect).list());
                    }
                    return jsonObject;
                }
        ).collect(Collectors.toList()));
    }

    @Override
    public R<String> insert(RoleVo roleVo) {
        Role build = Role.builder().roleName(roleVo.getName()).build();
        save(build);
        roleVo.getIds().forEach(id ->
                iRoleResourceService.save(RoleResource.builder().resourceId(id).roleId(build.getId()).build())
        );
        iRoleResourceService.init();
        return R.ok(null);
    }

    @Override
    public R<String> update(RoleVo roleVo) {
        lambdaUpdate().eq(Role::getId, roleVo.getId()).set(Role::getRoleName, roleVo.getName()).update();
        iRoleResourceService.lambdaUpdate().eq(RoleResource::getRoleId, roleVo.getId()).remove();
        roleVo.getIds().forEach(id ->
                iRoleResourceService.save(RoleResource.builder().resourceId(id).roleId(roleVo.getId()).build())
        );
        iRoleResourceService.init();
        return R.ok(null);
    }

    @Override
    public List<Role> getByUserId(int id) {
        List<Integer> roleIds = iUserRoleService.lambdaQuery().eq(UserRole::getUserId, id).list().stream().map(UserRole::getRoleId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(roleIds)) {
            return lambdaQuery().in(Role::getId, roleIds).list();
        }
        return null;
    }

    @Override
    public R<Map<Object, Object>> list(RolePage rolePage) {
        LambdaQueryChainWrapper<Role> rw = lambdaQuery();
        if (StrUtil.isNotBlank(rolePage.getName())) {
            rw.like(Role::getRoleName, rolePage.getName());
        }
        rw.orderByDesc(Role::getId);
        Page<Role> page = new Page<>(rolePage.getPageNum(), rolePage.getPageSize());
        List<Role> records = rw.page(page).getRecords();
        List<JSONObject> authority = records.stream().map(role -> {
            List<Integer> collect = iRoleResourceService.lambdaQuery().eq(RoleResource::getRoleId, role.getId()).list().stream().map(RoleResource::getResourceId).collect(Collectors.toList());
            return JSONUtil.parseObj(role).set("resource", iResourceService.lambdaQuery().in(Resource::getId, collect).list());
        }).collect(Collectors.toList());
        Map<Object, Object> build = MapUtil.builder().put("records", authority).put("total", page.getTotal()).build();
        return R.ok(build);
    }
}
